<template>
  <div class="medical-record-fields-container">
    <div class="header">
      <span class="title">病历字段</span>
      <div style="position: relative">
        <el-button
          class="settings-button"
          @click="onSetting"
          v-if="meaicalRecognition.activeName_1 == '1'"
          >设置</el-button
        >
        <div class="medical-record" v-if="isMedicalRecord">
          <medicalRecord
            @visible="onVisible"
            ref="medicalRecordRef"
            @checkList="settingsCheckList"
            :chineseFields="chineseFields"
          ></medicalRecord>
        </div>
      </div>
    </div>
    <table class="fields-table">
      <tr v-for="(field, index) in fields" :key="field.uuid">
        <td class="field-name" style="width: 100px">{{ field.name }}</td>
        <td class="field-action">
          <div style="display: flex; justify-content: space-between">
            <div
              style="
                position: relative;
                display: flex;
                align-items: center;
                justify-content: space-between;
                width: 80%;
              "
            >
              <div
                style="
                  width: 100%;
                  position: relative;
                  min-height: 43px;
                  line-height: 43px;
                "
                v-if="field?.fieldType == '1'"
                :contenteditable="
                  meaicalRecognition.activeName_1 == '1'
                    ? 'plaintext-only'
                    : false
                "
                @mousedown.capture="onFieldMouseDown(field.uuid)"
                @click.stop
                @focus="handleFocus(field)"
                @blur="handleBlur(field)"
                @input="onContentInput(field, $event)"
                @compositionstart="onCompositionStart"
                @compositionend="onCompositionEnd(field, $event)"
                :id="'outpatientfield' + field.uuid"
              >
                {{ field.content }}
              </div>
              <!-- <div
              style="width: 80%; position: relative"
              v-if="field?.fieldType == '1' && !isType"
              :contenteditable="false"
              :id="'field' + field.fieldId"
            >
              {{ field.content }}
            </div> -->
              <div
                class="shortcut"
                :id="'outpatientshortcut' + field.uuid"
                v-if="focusedField === field.uuid && field?.isRecom == '1'"
                contenteditable="false"
                @click.stop
              >
                <SymptomList
                  @onClose="onClose"
                  :symptomList="symptomList"
                  v-if="field?.fieldStyle == '2'"
                  @onSymptom="onSymptom"
                  @onCloseDel="onCloseDel"
                ></SymptomList>

                <Medical
                  :medicalList="symptomList"
                  @on-close="onClose"
                  @onSymptom="onSymptom"
                  @onCloseDel="onCloseDel"
                  v-if="field?.fieldStyle == '3'"
                ></Medical>
              </div>
              <div style="width: 100%" v-if="field?.fieldType == '2'">
                <el-date-picker
                  type="date"
                  placeholder="选择日期"
                  v-model="field.content"
                  v-if="meaicalRecognition.activeName_1 == '1'"
                />
                <span v-else>{{ field.content }}</span>
              </div>
            </div>
            <div style="display: flex; justify-content: end">
              <div
                style="cursor: pointer"
                class="action-icon"
                :class="{ recording: field.name === currentRecording }"
                @click="toggleVoiceInput(field.name, field.fieldId)"
                v-if="
                  field.isVoice == '1' && meaicalRecognition.activeName_1 == '1'
                "
              >
                <el-icon style="vertical-align: middle">
                  <Microphone />
                </el-icon>

                <span style="vertical-align: middle; font-size: 14px">
                  语音录入</span
                >
              </div>
              <div v-if="field?.isImage == '1'">
                <ImageUpload
                  :fieldId="field.fieldId"
                  :fieldName="field.name"
                  :fieldCode="field.fieldCode"
                  :isRequired="field.isRequired"
                  :fieldImages="field.fieldImages"
                  :activeName_1="meaicalRecognition.activeName_1"
                  @change="(value) => onUpload(value, field)"
                ></ImageUpload>
              </div>
              <div
                v-show="
                  field?.isPulse == '1' &&
                  meaicalRecognition.activeName_1 == '1'
                "
                style="text-align: right; cursor: pointer; position: relative"
                class="venation"
                @click.stop="toggleVenation(field.uuid)"
              >
                <img
                  src="@/assets/icon/icon_maixiang_nor.svg"
                  alt=""
                  style="vertical-align: sub; margin-right: 5px"
                />脉象选择
                <div
                  class="venation_box"
                  :class="{
                    'venation_box--top': shouldShowVenationOnTop(field.uuid),
                  }"
                  v-if="venationId === field.uuid && isVenationModal"
                >
                  <Venation
                    @click.stop
                    @closeModal="closeModal"
                    @onConfirm="(value) => onConfirm(value, field)"
                  ></Venation>
                </div>
              </div>
            </div>
          </div>
          <div v-if="field?.isImage == '1'">
            <div class="image-list" v-if="field.fieldImages">
              <div
                v-for="(image, index) in getImageList(field.fieldImages)"
                :key="index"
                class="image-item"
              >
                <img :src="image" />
                <div class="image-overlay" @click="removeImage(index, field)">
                  <div class="delete-icon" v-if="meaicalRecognition.activeName_1=='1'">×</div>
                </div>
              </div>
            </div>
          </div>
        </td>
      </tr>
    </table>
    <div
      style="
        margin-top: 10px;
        display: flex;
        padding: 8px 16px 8px 16px;
        border-radius: 5px;
      "
      class="fields-table"
    >
      <div class="field-name" style="width: 100px">医嘱事项</div>
      <div
        class="field-action"
        style="vertical-align: middle; width: 100%; position: relative"
      >
        <!-- <div
          style="width: 80%; position: relative"
          :contenteditable="meaicalRecognition.activeName_1 == '1'"
          @focus="handleFocus1('doctorAdvice1')"
          @blur="handleBlurDoctorAdvice"
          @input="onContentInputDoctorAdvice($event)"
          @compositionstart="onCompositionStart"
          @compositionend="onCompositionEndDoctorAdvice($event)"
          :id="'field1' + '88888'"
        >
          {{ doctorAdvice1 }}
        </div> -->
        <DoctorAdviceSelect
          v-model="doctorAdvice1"
          :placeholder="'医嘱事项，支持多选，用中文逗号分隔'"
          :delimiter="'，'"
          :extra-delimiters="[',', '， ', ', ', '、']"
          :deduplicate="false"
          selection-mode="append"
          :isdisabled="meaicalRecognition.activeName_1 != '1' ? true : false"
        />
      </div>
    </div>
    <div class="tab-content" style="height: 100px"></div>

    <voice
      ref="voiceRef"
      :currentRecording="currentRecording"
      @startRecording="startRecording"
      @stopRecording="stopRecording"
      @recordingStop="recordingStop"
    ></voice>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed } from 'vue';
import DoctorAdviceSelect from '@/components/DoctorAdviceSelect.vue';
import { Microphone, VideoPause } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import type {
  MedicalRecordField,
  FieldTreeNode,
} from '@/types/medicalRecordField';
import stores from '@/store';
import voice from './voice.vue';
import { v4 as uuidv4 } from 'uuid';
const directoryRef = ref<any>();
// 组件引用
const medicalRecordRef = ref<any>(null);
const voiceRef = ref<InstanceType<typeof voice> | null>(null);
const medicalFieldStore = stores.useMedicalRecordFieldStore();
const useBaseDataStore = stores.useBaseDataStore();
const templateDialog = ref(false);
const isVenationModal = ref(false);
const isType = ref<boolean>(false); // 默认类型为中文
const isMedical = ref<boolean>(false);
const meaicalRecognition = defineProps<{
  fieldList: any;
  dataType: string;
  doctorAdvice: string;
  activeName_1: string;
}>();
const activeName = ref('1');
const activeName_1 = ref('1');
const currentRecording = ref('');
const focusedField = ref<string | null>(null);
const isComposing = ref(false); // 中文输入法组合输入状态
const voiceld = ref<string | null>(null); // 用于存储当前聚焦的字段ID
const venationId = ref<string | null>(null); // 用于存储当前选中的脉象ID
// 在获得焦点的同一次点击中，跳过一次文档点击处理，避免误触发关闭逻辑
const skipNextDocumentClick = ref(false);
// 明确指定 recognition 的类型为 SpeechRecognition 或 null
// 声明全局 SpeechRecognition 类型
declare global {
  interface Window {
    webkitSpeechRecognition: any;
    SpeechRecognition: any;
  }
}
type SpeechRecognition = typeof window.webkitSpeechRecognition;
// 计算属性：从store获取字段数据
const fields = ref<any[]>([]);
const recognition = ref<SpeechRecognition | null>(null);
const isSupported = ref(false);
const isMedicalRecord = ref(false);
const newFormatType = ref('western'); // 默认格式为中文
const chineseFields = ref<MedicalRecordField[]>([]); //病历默认勾选字段
const westernFields = ref<MedicalRecordField[]>([]); //西文
const selectedField = ref<MedicalRecordField[]>([]);
const optionGroupList = ref<MedicalRecordField[]>([]);
const symptomList = ref<FieldTreeNode[]>([]); //症状
const doctorAdvice1 = ref('');
const emit = defineEmits(['voice-result', 'recording-status']);
// 医嘱枚举（保持响应式，避免组件挂载后枚举异步加载不到的问题）
const doctorAdviceEnum = computed(() => {
  const list = useBaseDataStore.getDOCTORADVICEEnumData('DOCTOR_ADVICE');
  return Array.isArray(list) ? list : [];
});
watch(
  () => meaicalRecognition.fieldList,
  (newVal) => {
    let allFields = medicalFieldStore.getAllFields;
    //console.log(meaicalRecognition.fieldList);
    doctorAdvice1.value = meaicalRecognition.doctorAdvice || '';
    if (
      meaicalRecognition.fieldList &&
      meaicalRecognition.fieldList.length > 0
    ) {
      allFields = meaicalRecognition.fieldList;
      fields.value = allFields.map((field) => {
        // 根据 fieldScope 选择对应的数据源
        let sourceFields;
        if (field.fieldScope === '1') {
          sourceFields = medicalFieldStore.chineseFields;
        } else if (field.fieldScope === '2') {
          sourceFields = medicalFieldStore.westernFields;
        } else {
          sourceFields = medicalFieldStore.westernFields; // 默认使用中医字段
        }
        // 查找匹配的字段，获取 treeList
        const matchedField = sourceFields?.find(
          (storeField) => storeField.fieldName === field.fieldName
        );

        return {
          ...field,
          name: field.fieldName,
          action: field.isVoice === '1', // 支持语音的字段显示语音按钮
          content: field?.fieldValue || '',
          fieldId: field.fieldId,
          fieldCode: field.fieldCode,
          isRequired: field.isRequired === '1',
          fieldImages: field?.fieldImages ? field.fieldImages.split(',') : [],
          uuid: uuidv4(),
          treeList: matchedField?.treeList || [], // 添加 treeList
        };
      });
      //console.log(fields.value);

      chineseFields.value = fields.value.map((field) => field.fieldId);
      return;
    } else if (newFormatType.value === 'chinese') {
      allFields = medicalFieldStore.chineseFields.filter(
        (field) => field.isDefault == '1'
      );
    } else {
      allFields = medicalFieldStore.westernFields.filter(
        (field) => field.isDefault == '1'
      );
    }
    fields.value = allFields.map((field) => ({
      ...field,
      name: field.fieldName,
      action: field.isVoice === '1', // 支持语音的字段显示语音按钮
      content: '',
      fieldId: field.fieldId,
      fieldCode: field.fieldCode,
      isRequired: field.isRequired === '1',
      uuid: uuidv4(),
      fieldImages: field?.fieldImages ? field.fieldImages.split(',') : [],
    }));

    // 仅选中默认勾选的中医字段
    chineseFields.value =
      medicalFieldStore.westernFields
        ?.filter((item: any) => item?.isDefault == '1')
        .map((item: any) => item.fieldId) || [];
  },
  { immediate: true, deep: true }
);
// 判断脉象弹窗是否应该显示在上方
const shouldShowVenationOnTop = (uuid: any): boolean => {
  if (typeof window === 'undefined') return false;
  const fieldElement = document.getElementById(`outpatientfield${uuid}`);
  if (!fieldElement) return false;
  const rect = fieldElement.getBoundingClientRect();
  const windowHeight = window.innerHeight;
  const popupHeight = 300; // 弹窗预估高度
  return windowHeight - rect.bottom < popupHeight;
};
const getImageList = (fieldId: any) => {
  // 添加判断fieldId是否为数组的逻辑
  if (Array.isArray(fieldId)) {
    //console.log('fieldId is an array:', fieldId);
    return fieldId;
  }

  if (!fieldId || fieldId.length == 0) return [];
  return fieldId.split(',');
};
// 检查浏览器是否支持语音识别
const checkVoiceSupport = () => {
  if ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) {
    isSupported.value = true;
    const SpeechRecognition =
      window.SpeechRecognition || window.webkitSpeechRecognition;
    recognition.value = new SpeechRecognition();

    // 配置语音识别
    if (recognition.value) {
      recognition.value.continuous = true;
      recognition.value.interimResults = true;
      recognition.value.lang = 'zh-CN';
      recognition.value.maxAlternatives = 1;
    }

    // 监听识别结果
    recognition.value.onresult = (event: {
      resultIndex: any;
      results: string | any[];
    }) => {
      let finalTranscript = '';
      let interimTranscript = '';

      for (let i = event.resultIndex; i < event.results.length; i++) {
        const transcript = event.results[i][0].transcript;
        if (event.results[i].isFinal) {
          finalTranscript += transcript;
        } else {
          interimTranscript += transcript;
        }
      }

      // 更新对应字段的内容
      if (currentRecording.value && finalTranscript) {
        const field = fields.value.find(
          (f) => f.name === currentRecording.value
        );
        if (field) {
          field.content = (field.content + finalTranscript).trim();
          field.fieldValue = (field.content + finalTranscript).trim();
          // 发送结果给父组件
          emit('voice-result', {
            fieldName: currentRecording.value,
            content: field.content,
            isInterim: false,
          });
        }
      }

      // 发送临时结果
      if (currentRecording.value && interimTranscript) {
        emit('voice-result', {
          fieldName: currentRecording.value,
          content: interimTranscript,
          isInterim: true,
        });
      }
    };

    // 监听开始
    recognition.value.onstart = () => {
      emit('recording-status', {
        status: 'started',
        fieldName: currentRecording.value,
      });
    };

    // 监听错误
    recognition.value.onerror = (event: { error: any }) => {
      //console.error('语音识别错误:', event.error);
      let errorMsg = '语音识别错误';

      switch (event.error) {
        case 'no-speech':
          errorMsg = '未检测到语音，请重试';
          break;
        case 'audio-capture':
          errorMsg = '无法访问麦克风';
          break;
        case 'not-allowed':
          errorMsg = '麦克风访问被拒绝';
          break;
        case 'network':
          errorMsg = '网络错误，请检查网络连接';
          break;
        default:
          errorMsg = `语音识别错误: ${event.error}`;
      }

      //ElMessage.error(errorMsg);
      currentRecording.value = '';
      emit('recording-status', { status: 'error', error: event.error });
    };

    // 监听结束
    recognition.value.onend = () => {
      emit('recording-status', {
        status: 'ended',
        fieldName: currentRecording.value,
      });
      currentRecording.value = '';
    };
  } else {
    isSupported.value = false;
    ElMessage.warning(
      '您的浏览器不支持语音识别功能，请使用Chrome、Edge或Safari浏览器'
    );
  }
};
const closeModal = () => {
  venationId.value = null;
  isVenationModal.value = false;
};
// 移除图片
const removeImage = (index: number, field: any) => {
  const targetArray = Array.isArray(field.fieldImages)
    ? field.fieldImages
    : getImageList(field.fieldImages);

  // 确保操作的是原数组引用
  if (Array.isArray(targetArray)) {
    targetArray.splice(index, 1);
    //console.log(targetArray);
    // 保持为数组格式，不转换为字符串
    field.fieldImages = [...targetArray];
    // 强制触发响应式更新
    triggerRef(fields);
  }
};
// 统一格式化枚举：兼容可能的字段命名（itemName / label / text / value）
const normalizeAdviceList = () => {
  return doctorAdviceEnum.value.map((it: any) => {
    const itemName =
      it.itemName || it.label || it.text || it.name || it.value || '';
    return {
      ...it,
      itemName,
      value: itemName, // el-autocomplete 内部默认取 value 作为回填
    };
  });
};

const createFilter = (query: string) => {
  const lower = query.toLowerCase();
  return (row: any) => row.itemName?.toLowerCase().includes(lower);
};

const querySearch = (queryString: string, cb: (arg: any[]) => void) => {
  const source = normalizeAdviceList();
  if (!queryString) {
    cb(source.slice(0, 50)); // 默认显示前 50 条，避免过长
    return;
  }
  const results = source.filter(createFilter(queryString));
  cb(results.slice(0, 50));
};
// 穴位确认时间
// 穴位确认时间
const onConfirm = (value: any, field: any) => {
  //console.log('确认穴位', value);
  isVenationModal.value = false;
  venationId.value = null;
  // 将传入的 value 转成可读字符串并追加到现有内容
  let strValue = '';
  if (value == null) {
    strValue = '';
  } else if (value instanceof Set) {
    strValue = Array.from(value as Set<any>)
      .map((v) => String(v))
      .join('，');
  } else if (Array.isArray(value)) {
    strValue = (value as any[]).map((v) => String(v)).join('，');
  } else if (typeof value === 'object') {
    const v: any = value;
    const maybe = v?.label ?? v?.text ?? v?.name;
    strValue = maybe ? String(maybe) : JSON.stringify(value);
  } else {
    strValue = String(value);
  }

  if (!strValue) return;

  const sep = '，';
  const prev = (field.content ?? '').toString().trim();
  const needsComma = prev && !/[，,]$/.test(prev);
  const next = prev ? `${prev}${needsComma ? sep : ''}${strValue}` : strValue;
  field.content = next;
  field.fieldValue = next;
  // isMedicalRecord.value = false;
};
// 图片上传回调方法
const onUpload = (value: any, field: any) => {
  // 保持为数组格式以确保响应式更新
  const imageUrls = value.map((item: { url: any }) => item.url);
  field.fieldImages = imageUrls;
  //console.log('图片上传成功', imageUrls);
  // 强制触发响应式更新
  triggerRef(fields);
};
//设置弹框
const onSetting = () => {
  isMedicalRecord.value = true;
  // medicalRecordRef.value?.open();
  // 这里可以打开设置弹框
  // ElMessage.info('设置功能尚未实现');
};
const onTemplate = () => {
  templateDialog.value = true;
};
// 获取焦点并设置光标到末尾
function focusWithCursorAtEnd(element: any) {
    // 先获取焦点
    element.focus();
    
    // 创建范围对象
    const range = document.createRange();
    // 选择元素的所有内容
    range.selectNodeContents(element);
    // 将范围折叠到末尾(false表示折叠到末尾)
    range.collapse(false);
    
    // 获取当前选择并清除现有选择
    const selection = window.getSelection();
    if (selection) {
     selection.removeAllRanges();
    // 添加新范围
    selection.addRange(range);
    }
}
// 关闭快捷输入
const onClose = () => {
  //console.log('关闭快捷输入');
  // editableDiv.focus();
  if (isMedical.value) {
    const fieldElement = document.getElementById(
      `outpatientfield${focusedField.value}`
    );
    // fieldElement?.focus();
    focusWithCursorAtEnd(fieldElement);
    isMedical.value = false;
  }
  focusedField.value = null;
  currentRecording.value = '';
};
const recordingStop = (value: string) => {
  //console.log('停止录音1111111111', value);
  // 可以将选中的症状添加到对应字段的内容中
  fields.value.forEach((f) => {
    if (f.uuid === voiceld.value) {
      f.content += `${value}`;
    }
  });
  // 强制触发响应式更新
  triggerRef(fields);
  // ElMessage.info('语音录入已停止');
};
// 保存模板弹框
const onSave = () => {};
// 切换语音录入状态
const toggleVoiceInput = (fieldName: string, uuid: any) => {
  if (!isSupported.value) {
    ElMessage.warning('您的浏览器不支持语音识别功能');
    return;
  }
  voiceld.value = uuid;
  voiceRef.value?.open1({
    fieldName,
  });
};
const toggleVenation = (uuid: any) => {
  isVenationModal.value = true;
  venationId.value = uuid;
};
// 文档点击：点击空白处关闭快捷面板
const handleDocumentClick = (e: MouseEvent) => {
  // 如果刚刚因为聚焦而标记了跳过，则本次点击直接忽略
  if (e && e.target) {
    const target = e.target as Element;
    if (!target.closest('.medical-record')) {
      isMedicalRecord.value = false;
    }
  }
  if (skipNextDocumentClick.value) {
    skipNextDocumentClick.value = false;
    return;
  }
  if (focusedField.value == null) return;
  if (typeof window === 'undefined') return;
  let target = e.target as Node;
  // 文本节点点击（如 contenteditable 内部文本），提升到元素节点
  if (target && target.nodeType === Node.TEXT_NODE) {
    target = (target.parentElement || target.parentNode) as Node;
  }
  const path = (
    typeof (e as any).composedPath === 'function'
      ? (e as any).composedPath()
      : []
  ) as EventTarget[];
  //console.log(`field${focusedField.value}`);

  const fieldEl = document.getElementById(
    `outpatientfield${focusedField.value}`
  );

  const shortcutEl = document.getElementById(
    `outpatientshortcut${focusedField.value}`
  );
  //console.log(fieldEl);
  //console.log(shortcutEl);
  // 点击在字段输入区或快捷面板内则不关闭
  const inField = !!(
    fieldEl &&
    (path.includes(fieldEl) || fieldEl.contains(target))
  );
  const inShortcut = !!(
    shortcutEl &&
    (path.includes(shortcutEl) || shortcutEl.contains(target))
  );
  if (inField || inShortcut) return;
  // 其余情况关闭
  onClose();
};
// contenteditable 输入同步到字段
const onContentInput = (field: any, e: Event) => {
  // 组合输入过程中不更新响应式，防止 caret 被重置
  if (isComposing.value) return;
  if (focusedField.value !== field.uuid) return;
  const target = e.target as HTMLElement;
  const text = target.innerText ?? '';
  // 编辑期仅维护临时值，避免触发视图重渲染
  field.fieldValue = text;
};
const onContentInputDoctorAdvice = (e: Event) => {
  if (isComposing.value) return;
  const target = e.target as HTMLElement;
  doctorAdvice1.value = target.innerText ?? '';
};
const onCompositionStart = () => {
  isComposing.value = true;
};
const onCompositionEnd = (field: any, e: Event) => {
  isComposing.value = false;
  onContentInput(field, e);
};
const onCompositionEndDoctorAdvice = (e: Event) => {
  isComposing.value = false;
  onContentInputDoctorAdvice(e);
};
const handleBlurDoctorAdvice = () => {
  if (isComposing.value) isComposing.value = false;
};
// 点击症状
// const onSymptom = (symptom: FieldTreeNode) => {
//   // 这里可以处理选中症状的逻辑
//   //console.log('选中的症状:', symptom);
//   // 可以将选中的症状添加到对应字段的内容中
//   fields.value.forEach((f) => {
//     if (f.fieldId === focusedField.value) {
//       f.content += `${symptom.text}`;
//     }
//   });
//   // 强制触发响应式更新
//   triggerRef(fields);
//   //console.log(fields.value);
// };
const onCloseDel = () => {
  console.log(focusedField.value);
  
  fields.value.forEach((f) => {
    if (f.uuid !== focusedField.value) return;
    if (f.content == '\n') {
      f.content = '';
    }
    f.content = f.content.slice(0, -1);
    f.fieldValue = f.content.slice(0, -1);
  });
};
// 点击症状（支持单个或数组，追加而不覆盖，自动去重）
const onSymptom = (symptom: any, category: any) => {
  //console.log('选中的症状:', symptom);
  fields.value.forEach((f) => {
    if (f.uuid !== focusedField.value) return;
    if (f.content == '\n') {
      f.content = '';
    }
    const prevRaw = (f.content ?? '').toString().trim();
    const existingSet = new Set(
      prevRaw
        ? prevRaw
            .split(/[，,]+/)
            .map((s: string) => s.trim())
            .filter(Boolean)
        : []
    );

    // 统一整理本次传入的症状列表
    // let incoming: string[] = [];
    // if (Array.isArray(symptom)) {
    //   incoming = symptom
    //     .map((s: any) => (s?.text ?? s)?.toString().trim())
    //     .filter(Boolean);
    // } else {
    //   incoming = [(symptom?.text ?? symptom)?.toString().trim()].filter(
    //     Boolean
    //   );
    // }

    // // 过滤掉已经存在的，避免重复
    // const newItems = incoming.filter((it) => !existingSet.has(it));
    // if (newItems.length === 0) return; // 没有新增内容则不更新
    // const sep = '，';
    let data = '';
    symptom.forEach((item: { type: any; text: any }) => {
      if (item.type) {
        if (f.isPrefix == '1') {
          data += `${category.text + item.text}`;
        } else {
          data += `${item.text}`;
        }
      } else {
        if (!f.content) {
          if (f.isPrefix == '1') {
            data += `${category.text + item.text}`;
          } else {
            data += `${item.text}`;
          }
        } else {
          if (f.isPrefix == '1') {
            data += `，${category.text + item.text}`;
          } else {
            data += `，${item.text}`;
          }
        }
      }
    });
    // const prefix = prevRaw
    //   ? /[，,]$/.test(prevRaw)
    //     ? prevRaw
    //     : prevRaw + sep
    //   : '';
    // const appended = prefix + newItems.join(sep);
    f.content += data;
    f.fieldValue += data;
  });

  triggerRef(fields); // 触发视图更新
};

// 添加目录
const onAddDirectory = () => {
  if (directoryRef.value) {
    directoryRef.value.open1({
      groupName: '',
      templateCategory: activeName.value,
      templateType: activeName_1.value,
    });
  }
};
// 开始录音
const startRecording = (fieldName: string) => {
  try {
    if (currentRecording.value) {
      // 如果正在录制其他字段，先停止
      stopRecording();
    }

    currentRecording.value = fieldName;
    recognition.value.start();
    ElMessage.success(`开始录入 ${fieldName}`);
  } catch (error) {
    //console.error('开始录音失败:', error);
    //ElMessage.error('开始录音失败');
    currentRecording.value = '';
  }
};

// 停止录音
const stopRecording = () => {
  if (recognition.value && currentRecording.value) {
    // recognition.value?.stop();
    ElMessage.info(`停止录入 ${currentRecording.value}`);
  }
};
// 处理焦点事件
const handleFocus = (field: any) => {
  symptomList.value = field;
  focusedField.value = field.uuid;
  isMedical.value = true;
  //console.log('11111111111', focusedField.value);
};

// 在字段内按下鼠标，标记跳过接下来一次全局点击处理
const onFieldMouseDown = (uuid: any) => {
  // 若当前要聚焦的就是该字段，则跳过即将到来的一次 document click
  if (focusedField.value == null || focusedField.value === uuid) {
    skipNextDocumentClick.value = true;
  }
};
const handleFocus1 = (field: any) => {};

// 判断弹框是否应该显示在上方
const shouldShowOnTop = (uuid: number): boolean => {
  if (typeof window === 'undefined') return false;

  const fieldElement = document.getElementById(`outpatientfield${uuid}`);
  if (!fieldElement) return false;

  const rect = fieldElement.getBoundingClientRect();
  const windowHeight = window.innerHeight;

  // 弹框预估高度（可根据实际情况调整）
  const popupHeight = 300;

  // 如果下方空间不足显示弹框，则显示在上方
  return windowHeight - rect.bottom < popupHeight;
};

const handleBlur = (field: any) => {
  // 失焦时一次性将 DOM 文本回写到响应式数据，避免输入期频繁重渲染导致光标跳动
  const el = document.getElementById(
    `outpatientfield${field.uuid}`
  ) as HTMLElement | null;
  const text = el?.innerText ?? '';
  field.content = text;
  field.fieldValue = text;
  if (isComposing.value) {
    isComposing.value = false;
  }
};

// 获取病历字段
const settingsCheckList = (checkList: any, newFormat: string) => {
  // checkList.value: 选中的 fieldId 列表
  const selectedIds: any[] = checkList?.value || [];
  chineseFields.value = selectedIds; // 保持原有赋值（命名历史保留）
  const selectedIdSet = new Set(selectedIds);

  // 选择数据源
  const sourceFields =
    newFormat === 'chinese'
      ? medicalFieldStore.chineseFields
      : medicalFieldStore.westernFields;

  // 现有字段映射，便于复用原对象（保留 content、fieldImages 等用户输入）
  const existingMap = new Map<number, any>(
    fields.value.map((f) => [f.fieldId, f])
  );

  const newFields: any[] = [];
  // 按数据源原始顺序（或源字段顺序）重建选中集合
  for (const sf of sourceFields) {
    if (!selectedIdSet.has(sf.fieldId)) continue; // 未勾选跳过
    if (existingMap.has(sf.fieldId)) {
      // 复用已有，保留用户已输入的 content 等
      newFields.push(existingMap.get(sf.fieldId));
    } else {
      // 新增：初始化 content 为空，其它属性按源字段构建
      newFields.push({
        ...sf,
        name: sf.fieldName,
        action: sf.isVoice === '1',
        content: '',
        fieldId: sf.fieldId,
        fieldCode: sf.fieldCode,
        isRequired: sf.isRequired === '1',
        fieldImages: sf?.fieldImages ? sf.fieldImages.split(',') : [],
        treeList: sf?.treeList || [],
      });
    }
  }

  // 替换列表：已取消勾选的自动被移除；保持新引用以触发下游依赖
  fields.value = newFields;
  newFormatType.value = newFormat;
};
// 获取字段内容
const getFieldContent = (fieldName: string) => {
  const field = fields.value.find((f) => f.name === fieldName);
  return field ? field.content : '';
};

// 设置字段内容
const setFieldContent = () => {
  // const field = fields.value.find(f => f.name === fieldName);
  // if (field) {
  //   field.content = content;
  // }
};
const onVisible = () => {
  isMedicalRecord.value = false;
  // 这里可以处理弹框关闭后的逻辑
};
// 清空字段内容
const clearFieldContent = () => {
  // const field = fields.value.find(f => f.name === fieldName);
  // if (field) {
  //   field.content = '';
  // }
};

// 获取所有字段内容
const getAllFieldsContent = () => {
  // return fields.value.reduce((acc, field) => {
  //   acc[field.name] = field.content;
  //   return acc;
  // }, {});
};

onMounted(async () => {
  checkVoiceSupport();
  if (typeof document !== 'undefined') {
    document.addEventListener('mousedown', handleDocumentClick);
  }
});

onUnmounted(() => {
  if (recognition.value && currentRecording.value) {
    recognition.value.stop();
  }
  if (typeof document !== 'undefined') {
    document.removeEventListener('mousedown', handleDocumentClick);
  }
});

// 暴露方法供父组件使用
defineExpose({
  getFieldContent,
  setFieldContent,
  clearFieldContent,
  getAllFieldsContent,
  fields,
  stopRecording,
  startRecording,
  isSupported: () => isSupported.value,
  isRecording: () => !!currentRecording.value,
  doctorAdvice1,
});
</script>

<style lang="scss" scoped>
/* 去除 contenteditable 焦点外框（支持 plaintext-only 与普通 true） */
[contenteditable]:focus,
[contenteditable]:focus-visible {
  outline: none !important;
  box-shadow: none !important;
}

.shortcut {
  position: absolute;
  top: 100%;
  right: 0;
  width: 100%;
  z-index: 10;
  border-radius: 4px;
}

.shortcut-top {
  top: auto;
  bottom: 40px;
}
.venation_box {
  position: absolute;
  top: 40px;
  right: 0px;
  z-index: 10000;
}
.venation_box--top {
  top: auto;
  bottom: 40px;
}
.medical-record-fields-container {
  background-color: #fff;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  border-radius: 12px 12px 0px 0px;
  overflow: auto;
  height: 570px;
  .header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 16px;
    position: relative;
    .title {
      font-weight: bold;
    }

    .settings-button {
      padding: 4px 8px;
      border: 1px solid #ccc;
      border-radius: 4px;
      background-color: #fff;
      cursor: pointer;
    }
  }

  .fields-table {
    width: 100%;
    border-collapse: collapse;
    background: rgba(22, 173, 164, 0.08);

    tr {
      border-bottom: 1px solid #f0f0f0;

      &:last-child {
        border-bottom: none;
      }

      td {
        padding: 8px 16px 8px 16px;
        vertical-align: middle;
        border-right: 1px solid #f0f0f0;

        &:last-child {
          border-right: none;
        }
        .field-name {
          font-weight: 400;
          font-size: 14px;
          color: rgba(0, 0, 0, 0.6);
        }

        .field-action {
          text-align: right;
          .action-icon {
            display: inline-flex;
            align-items: center;
            gap: 4px;
            color: #666;
            cursor: pointer;
            transition: all 0.3s ease;
            padding: 4px 8px;
            border-radius: 4px;
            font-size: 12px;

            &:hover {
              color: var(--el-color-primary);
              background-color: rgba(64, 158, 255, 0.1);
            }

            &.recording {
              color: #f56c6c;
              background-color: rgba(245, 108, 108, 0.1);
              animation: pulse 1.5s infinite;
            }

            .recording-icon {
              color: #f56c6c;
            }

            .el-icon {
              font-size: 14px;
            }
          }
        }

        @keyframes pulse {
          0% {
            opacity: 1;
          }
          50% {
            opacity: 0.5;
          }
          100% {
            opacity: 1;
          }
        }

        @keyframes recordingPulse {
          0%,
          100% {
            box-shadow: 0 0 0 0 rgba(245, 108, 108, 0.7);
          }
          50% {
            box-shadow: 0 0 0 10px rgba(245, 108, 108, 0);
          }
        }
      }
    }
  }
}
.venation {
  height: 17px;
  font-family: Microsoft YaHei, Microsoft YaHei;
  font-weight: 400;
  font-size: 13px;
  text-align: right;
  font-style: normal;
  text-transform: none;
}
.medical-record {
  min-width: 550px;
  position: absolute;
  top: 10px;
  right: 0;
  z-index: 10;
  height: 400px;
}
::v-deep(.el-input__wrapper) {
  background-color: transparent;
  border: none;
  box-shadow: none;
}
.image-list {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  flex: 1;
}
.image-item {
  position: relative;
  width: 120px;
  height: 120px;
  border: 2px dashed #d9d9d9;
  border-radius: 6px;
  overflow: hidden;
  background: #fafafa;

  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .image-overlay {
    position: absolute;
    top: 0px;
    right: 0px;
    background: rgba(0, 0, 0, 0.5);
    border-radius: 0 0 0 6px;
    transition: opacity 0.3s ease;

    .delete-icon {
      color: white;
      font-size: 13px;
      cursor: pointer;
    }
  }
}
</style>
